package xyz.hubery.listener;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
import xyz.hubery.model.Constants;
import xyz.hubery.pojo.Orders;
import xyz.hubery.pojo.SeckillGoods;
import xyz.hubery.pojo.StockRecord;
import xyz.hubery.service.SeckillService;

import java.util.Date;

/**
 * redis监听类继承KeyExpirationEventMessageListener
 */
@Slf4j
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillService seckillService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }


    /**
     * 现在一共有两种类型的过期key
     * 第一种：过期的商品数据：seckillGoods:goodId，说明秒杀结束，需要更新数据库库存信息
     * 第二种：过时的订单数据：order:orderId，说明订单支付失败，需要回退库存
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {

        // 判断当前过期key的 类型
        String expiredKey = message.toString();
        if (expiredKey.startsWith("seckillGoods:")) { // 说明是秒杀商品数据
            log.info("秒杀借宿，更新库存");
            // 从过期的key中截取商品id
            Long goodId = Long.parseLong(expiredKey.substring("seckillGoods:".length()));
            // 获取该商品库存
            Integer stockCount = (Integer) redisTemplate.opsForValue().get("seckillStock:" + goodId);
            // 删除库存数据
            redisTemplate.delete("seckillStock:" + goodId);
            // 更新数据库库存
            seckillService.updateStock(goodId, stockCount, true);
            // 添加一条库存变更记录
            StockRecord stockRecord = new StockRecord();
            stockRecord.setGoodsId(goodId);
            stockRecord.setChangeQuantity(stockCount);
            stockRecord.setOperationType(5);
            stockRecord.setOperationTime(new Date());
            stockRecord.setOperator("system");
            stockRecord.setRemark("秒杀结束回写库存");
            rocketMQTemplate.syncSend(Constants.SYNC_STOCK_OPERATION_TOPIC, stockRecord);
        } else if (expiredKey.startsWith("orders:")) { // 说明是订单过期数据
            log.info("回退库存");

            // 拿到复制订单信息
            Orders orders = (Orders) redisTemplate.opsForValue().get(expiredKey + "_copy");
            Long goodId = orders.getCartGoods().get(0).getGoodId(); // 产品id
            Integer num = orders.getCartGoods().get(0).getNum(); // 产品数量

            // 查询秒杀商品
            SeckillGoods seckillGoods = seckillService.findSeckillGoodsByRedis(goodId);

            // 回退库存(回退到缓存中的库存还是数据库？
            // 如果秒杀商品已过期，则回退到数据库，否则回退到缓存中的库存，因为秒杀过程中库存变动都是在缓存中进行
            if (Boolean.TRUE.equals(redisTemplate.hasKey("seckillGoods:" + goodId))) { // 秒杀商品未过期
                Integer stockCount = (Integer) redisTemplate.opsForValue().get("seckillStock:" + goodId);
                redisTemplate.opsForValue().set("seckillStock:" + goodId, stockCount + num); // 回退库存
            } else { // 秒杀商品已过期,则回退数据库库存
                seckillService.updateStock(goodId, num, false);
                // 添加一条库存变更记录
                StockRecord stockRecord = new StockRecord();
                stockRecord.setOrderId(orders.getId());
                stockRecord.setGoodsId(goodId);
                stockRecord.setChangeQuantity(num);
                stockRecord.setOperationType(4);
                stockRecord.setOperationTime(new Date());
                stockRecord.setOperator(orders.getBuyerNick());
                stockRecord.setRemark("订单未及时支付");
                rocketMQTemplate.syncSend(Constants.SYNC_STOCK_OPERATION_TOPIC, stockRecord);
            }

            // 删除复制订单数据
            redisTemplate.delete(expiredKey + "_copy");
        }
    }
}
